package com.multicampus.simplewiki.model;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.PostPersist;
import javax.persistence.PostRemove;
import javax.persistence.PostUpdate;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;

import com.multicampus.simplewiki.search.DocumentIndexer;
import com.multicampus.simplewiki.search.Indexer;

@Entity
public class Document {
	private int id;
	private String title;
	private String content;
	private String tags;
	private int version;
	private Timestamp creationDate;
	private Timestamp updateDate;

	private Document parent;
	private Collection<Document> children;

	private Document current;
	private Collection<Document> histories;
	private Collection<TrackBack> trackbacks;
	private User author;

	public Document() {
		this.version = 0;
	}

	public Document(int id, String title, String content, String tags, Timestamp creationDate, Timestamp updateDate) {
		this.id = id;
		this.title = title;
		this.content = content;
		this.tags = tags;
		this.creationDate = creationDate;
		this.updateDate = updateDate;
		this.version = 0;
	}

	@Id
	@GeneratedValue
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	@Lob
	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public Timestamp getCreationDate() {
		return creationDate;
	}

	public void setCreationDate(Timestamp creationDate) {
		this.creationDate = creationDate;
	}

	public Timestamp getUpdateDate() {
		return updateDate;
	}

	public void setUpdateDate(Timestamp updateDate) {
		this.updateDate = updateDate;
	}

	public String getTags() {
		return tags;
	}

	public void setTags(String tags) {
		this.tags = tags;
	}

	public int getVersion() {
		return version;
	}

	public void setVersion(int version) {
		this.version = version;
	}

	@ManyToOne(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
	@JoinColumn(name = "parent_fk")
	public Document getParent() {
		return parent;
	}

	public void setParent(Document parent) {
		this.parent = parent;
	}

	@OneToMany(mappedBy = "parent", cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
	public Collection<Document> getChildren() {
		return children;
	}

	public void setChildren(Collection<Document> children) {
		this.children = children;
	}

	@ManyToOne(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
	@JoinColumn(name = "author_fk")
	public User getAuthor() {
		return author;
	}

	public void setAuthor(User author) {
		this.author = author;
	}

	@OneToMany(mappedBy = "current")
	public Collection<Document> getHistories() {
		return histories;
	}

	public void setHistories(Collection<Document> histories) {
		this.histories = histories;
	}

	@ManyToOne(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
	@JoinColumn(name = "current_fk")
	public Document getCurrent() {
		return current;
	}

	public void setCurrent(Document current) {
		this.current = current;
	}

	@OneToMany(mappedBy = "document")
	public Collection<TrackBack> getTrackbacks() {
		return trackbacks;
	}

	public void setTrackbacks(Collection<TrackBack> trackbacks) {
		this.trackbacks = trackbacks;
	}
	
	public void addTrackback(TrackBack trackback){
		if(this.trackbacks == null)
			this.trackbacks = new ArrayList<TrackBack>();
		
		this.trackbacks.add(trackback);
	}

	public void makeHistory() {
		Document history = new Document();
		history.setTitle(this.title);
		history.setContent(this.content);
		history.setCreationDate(this.creationDate);
		history.setUpdateDate(this.updateDate);
		history.setVersion(this.version);
		history.setAuthor(this.author);

		addHistory(history);
	}

	public void addHistory(Document history) {
		if (histories == null) {
			histories = new ArrayList<Document>();
		}

		history.setCurrent(this);
		histories.add(history);
	}

	@PreUpdate
	public void autoUpdate() {
		setUpdateDate(new Timestamp(System.currentTimeMillis()));
		setVersion(this.version + 1);
	}

	@PrePersist
	public void autoCreate() {
		setCreationDate(new Timestamp(System.currentTimeMillis()));
		setVersion(0);
	}

	@PostPersist
	public void onPersist() {
		try{
			Indexer<Document> indexer = DocumentIndexer.getInstance();
			indexer.addIndex(this);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	@PostUpdate
	public void onUpdate(){
		try{
			Indexer<Document> indexer = DocumentIndexer.getInstance();
			indexer.updateIndex(this);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	@PostRemove
	public void onDelete(){
		try{
			Indexer<Document> indexer = DocumentIndexer.getInstance();
			indexer.deleteIndex(this);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}
